/**
 * 
 */
package org.log4jconfig.xml.editor.contentassist.delegate;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.core.CreateTypeHierarchyOperation;
import org.eclipse.jdt.ui.ISharedImages;
import org.eclipse.wst.xml.ui.internal.contentassist.ContentAssistRequest;
import org.log4jconfig.xml.editor.utils.JdtUtils;

/**
 * @author Xi
 * 
 */
@SuppressWarnings("restriction")
public abstract class AbstractTypeContentAssistDelegatedProcessor extends
		AbstractContentAssistDelegatedProcessor {

	private String typeName = null;
	private IType type = null;
	private Map<IJavaProject, ITypeHierarchy> hierarchiesCache = new HashMap<IJavaProject, ITypeHierarchy>();

	public AbstractTypeContentAssistDelegatedProcessor(String typeName) {
		this.typeName = typeName;
	}
	
	public void addAttributeValueProposals(
			ContentAssistRequest contentAssistRequest, String attributeName,
			String attributeCurrentValue, String attributeMatchValue)
			throws Exception {
		// content assist for the 'additivity' parameter value
		if ("class".equals(attributeName)) {
			ITypeHierarchy hierarchy = retrieveTypeAndHierarchies();
			// TODO : use progress monitor whenever it is possible ?
			// TODO : add hierarchy change listener + cache to avoid refresh
			// every time ?
			hierarchy.refresh(null);
			List<String> values = new ArrayList<String>();
			// only keep concrete classes from the retrieved type hierarchy.
			for (IType t : hierarchy.getAllSubtypes(type)) {
				if (t.isClass() && !Flags.isAbstract(t.getFlags())) {
					values.add(t.getFullyQualifiedName());
				}
			}
			// sort proposal values
			Collections.sort(values);
			for (String value : values) {
				addCompletionProposal(contentAssistRequest, value,
						attributeCurrentValue, attributeMatchValue,
						ISharedImages.IMG_OBJS_CLASS);

			}

		}
	}

	private ITypeHierarchy retrieveTypeAndHierarchies()
			throws JavaModelException {
		IJavaProject javaProject = JdtUtils.getCurrentJavaProject();
		if (type == null) {
			type = javaProject.findType(typeName);
		}
		ITypeHierarchy hierarchy = hierarchiesCache.get(javaProject); 
		if (hierarchy == null) {
			CreateTypeHierarchyOperation operation = new CreateTypeHierarchyOperation(type, null, javaProject, true);
			hierarchy = operation.getResult();
			hierarchiesCache.put(javaProject, hierarchy);
		}
		return hierarchy;
	}

}
